package com.eternal.base.protocol;

import com.eternal.framework.utils.KLog;

import java.nio.ByteBuffer;

public class StateMachine {
    private State now;
    private final ByteBuffer cache;
    private ByteBuffer buffer;
    private final Callback callback;

    public StateMachine(Callback callback) {
        cache = ByteBuffer.allocate(1024);
        this.callback = callback;
        now = sHead;
    }

    public void onNext(byte[] data) {
        cache.put(data);
        cache.flip();
        while (true) {
            if (now.onNext()) break;
        }
        cache.compact();
    }

    private final State sHead = new State() {
        @Override
        public boolean onNext() {
            if (cache.remaining() >= 4) {
                short head = cache.getShort();
                //0xa5 0x10
                if (head == -23280) {
                    head = cache.getShort();
                    buffer = ByteBuffer.allocate(10 + head + 2);
                    buffer.putShort((short) -23280);
                    buffer.putShort(head);
                    now = sLength;
                    //0x1e 0xff length 31
                } else if (head == 7935) {
                    buffer = ByteBuffer.allocate(31);
                    buffer.putShort(head);
                    now = sLength;
                }
                return false;
            }
            return true;
        }
    };

    private final State sLength = new State() {
        @Override
        public boolean onNext() {
            if (buffer.remaining() <= cache.remaining()) {
                int limit = cache.limit();
                cache.limit(cache.position() + buffer.remaining());
                buffer.put(cache);
                cache.limit(limit);
                if (callback != null) {
                    callback.onPacket(buffer.array());
                }
                now = sHead;
                return false;
            } else {
                buffer.put(cache);
                return true;
            }
        }
    };

    public interface Callback {
        void onPacket(byte[] packet);
    }
}
